<script setup lang="ts">
import { Search, Picture as IconPicture, Download, EditPen, PictureFilled, Plus, Share } from '@element-plus/icons-vue';
import { StudentAPI } from '@/api';
import { ElMessage, FormInstance, FormRules } from 'element-plus';
import type { UploadProps, UploadFile, UploadFiles, UploadUserFile } from 'element-plus';
import { ref, reactive, onMounted, nextTick, markRaw } from 'vue';
import { useDictionaryStore, useClassStore, useAuthStore } from '@/store';
import { httpBatch } from '@/util/http';
import FileSaver from 'file-saver';
import XLXS from 'xlsx';

const classStore = useClassStore();
const tableRef = ref<any>(null);
const dictionaryStore = useDictionaryStore();
const newList = ref<Vm.Dictionary[]>([]);
const formLabelWidth = '80px';
const searchModel = reactive<HttpPayload.Student>({
    stu_name: "",
    stu_cls_id: 0,
    stu_qualification: 0,
    begin: 0,
    pageSize: 3
});
const edit = reactive<{ isEdit: boolean, isStu: boolean, isClass: boolean, model: HttpPayload.StudentSearch, checkedItem: [] }>({
    isEdit: false,
    isStu: true,
    isClass: false,
    model: {
        stu_id: 0,
        stu_name: '',
        stu_avatar: '',
        stu_cls_id: null,
        stu_sex: 1,
        stu_phone: '',
        stu_phone2: '',
        stu_born: '',
        stu_qualification: 0,
        stu_school: '',
        stu_major: '',
        stu_address: '',
        stu_remark: ''
    },
    checkedItem: []
});
const disModel = reactive<HttpPayload.StudentAssignclass>({
    stu_id: null,
    stu_cls_id: null,
    stu_ids: [],
    type: 0
});
const studentList = ref<Vm.Student[]>([]);

const pagination = reactive({
    total: 0, currentPage: 1
});

const formRef = ref<FormInstance | null>(null);
//定制表单校验规则
const rules: FormRules = {
    stu_name: [
        { required: true, message: '*学生姓名不能为空', trigger: "blur" },
        { min: 1, max: 20, message: '*学生名长度1 - 20', trigger: "blur" }
    ],
    stu_sex: [
        { required: true, message: '*性别不能为空', trigger: "blur" }
    ],
    stu_phone: [
        { required: true, message: '*联系电话不能为空', trigger: "blur" },
        { min: 1, max: 11, message: '*联系电话长度1 - 11', trigger: "blur" }
    ],
    stu_phone2: [
        { required: true, message: '*备用电话不能为空', trigger: "blur" },
        { min: 1, max: 11, message: '*备用电话长度1 - 11', trigger: "blur" }
    ],
    stu_born: [
        { required: true, message: '*出生日期不能为空', trigger: "blur" },
        { min: 1, max: 10, message: '*出生日期长度1 - 10', trigger: "blur" }
    ],
    stu_qualification: [
        { required: true, message: '*学生学历不能为空', trigger: "blur" }
    ],
    stu_address: [
        { required: true, message: '*家庭地址不能为空', trigger: "blur" },
        { min: 3, max: 100, message: '*家庭地址长度3 - 100', trigger: "blur" }
    ],
}
const getData = async (fromPage1 = true) => {
    if (fromPage1) pagination.currentPage = 1
    searchModel.begin = (pagination.currentPage - 1) * searchModel.pageSize
    try {
        const { total, list } = await StudentAPI.get(searchModel)
        if (total > 0 && list.length === 0) {
            pagination.currentPage = Math.ceil(total / searchModel.pageSize)
            await getData(false);
            return;
        }
        pagination.total = total;
        studentList.value = list
    } catch (e) { console.log(e) }
};
onMounted(async () => {
    try {
        await httpBatch([() => dictionaryStore.init(), () => classStore.classInit(), () => getData()], true)
        dictionaryStore.list.forEach((item: Vm.Dictionary) => { if (item.dic_group_key === 'qualification') newList.value.push(item) })
    } catch (e) { }
});
const addStu = () => {
    formRef.value?.resetFields();
    edit.model.stu_name = '';
    edit.model.stu_avatar = '';
    edit.model.stu_cls_id = null;
    edit.model.stu_sex = 1;
    edit.model.stu_phone = '';
    edit.model.stu_phone2 = '';
    edit.model.stu_born = '';
    edit.model.stu_qualification = 0;
    edit.model.stu_school = '';
    edit.model.stu_major = '';
    edit.model.stu_address = '';
    edit.model.stu_remark = '';
    edit.isStu = true;
    nextTick(() => edit.isEdit = true)
};
const updateStu = (stu: HttpPayload.StudentSearch) => {
    formRef.value?.resetFields();
    edit.model.stu_name = stu.stu_name;
    edit.model.stu_avatar = stu.stu_avatar;
    edit.model.stu_cls_id = stu.stu_cls_id;     // 先赋值成null  点击开课 给他分配班级
    edit.model.stu_sex = stu.stu_sex;
    edit.model.stu_phone = stu.stu_phone;
    edit.model.stu_phone2 = stu.stu_phone2;
    edit.model.stu_born = stu.stu_born;
    edit.model.stu_qualification = stu.stu_qualification;
    edit.model.stu_school = stu.stu_school;
    edit.model.stu_major = stu.stu_major;
    edit.model.stu_address = stu.stu_address;
    edit.model.stu_remark = stu.stu_remark;
    edit.model.stu_id = stu.stu_id;
    edit.isStu = false;
    nextTick(() => edit.isEdit = true);
};
const save = async () => {
    try {
        await formRef.value?.validate();
        if (edit.model.stu_id === 0) {
            await StudentAPI.add(edit.model);
            ElMessage({ message: `学生'${edit.model.stu_name}'添加成功!`, type: "success" });
        } else {
            await StudentAPI.update(edit.model);
            ElMessage({ message: `学生'${edit.model.stu_name}'的信息修改成功..`, type: "success" });
        }
        edit.isEdit = false;
        await getData();
    } catch (e) { console.log(e) }
};
const distSingle = (data: HttpPayload.StudentSearch) => {
    disModel.type = 1;
    disModel.stu_id = data.stu_id;
    disModel.stu_ids = [];
    disModel.stu_cls_id = data.stu_cls_id
    nextTick(() => edit.isClass = true);
};
const distMult = () => {
    disModel.type = 2;
    disModel.stu_id = null;
    disModel.stu_cls_id = 0;
    edit.checkedItem.forEach(item => disModel.stu_ids.push(item.stu_id));
    nextTick(() => edit.isClass = true);
};
const saveDist = async () => {
    if (disModel.type === 1)
        await httpBatch([() => StudentAPI.assignClass(disModel), () => getData(false)], true);
    else
        await httpBatch([() => StudentAPI.assignClass(disModel), () => getData(false)], true);
    ElMessage({ message: `操作成功`, type: "success" });
    edit.isClass = false;
};
const isChecked = (v: []) => {
    edit.checkedItem = v;
};

//照片存档
const authStore = useAuthStore();
const isUpload = ref<boolean>(false);   //是否正在上传
const fileList = ref<UploadUserFile[]>(markRaw([]));
const avatarUpdateModel = reactive<HttpPayload.AvatarUpdate>({
    stu_id: 0, stu_avatar_old: null, stu_avatar_new: ""
});
//开始头像更新
const beginAvatarUpdate = (student: Vm.Student) => {
    avatarUpdateModel.stu_id = student.stu_id;
    avatarUpdateModel.stu_avatar_old = student.stu_avatar === null ? null : student.stu_avatar
    fileList.value = markRaw([]);
    isUpload.value = true;
};
//文件上传前的校验
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
    if (rawFile.type !== 'image/jpeg' && rawFile.type !== 'image/png') {
        ElMessage.error('上传头像必须是jpg或png!');
        return false;
    } else if (rawFile.size / 1024 / 1024 > 2) {
        ElMessage.error('图片大小不能超过2MB!');
        return false;
    }
    return true;
};
//文件上传成功的回调函数
const successHandler = (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => {
    avatarUpdateModel.stu_avatar_new = response.data;
    if (avatarUpdateModel.stu_avatar_old === null && uploadFiles.length > 1) uploadFiles.shift();  //删除第一个
    if (avatarUpdateModel.stu_avatar_old !== null && uploadFiles.length > 2) uploadFiles.splice(1, 1);  //删第二张，留最新的一张
    ElMessage.success('图片预上传成功!');
};
//更新新头像
const avatarUpdate = async () => {
    const newAvatarPath = await StudentAPI.avatarUpdate(avatarUpdateModel);
    console.log(newAvatarPath);
    isUpload.value = false;
    ElMessage.success('学生头像更新成功!');
};

//导出表格
const state = reactive({
    excelTitle: "表格标题1",
});
const exportClick = () => {
    // 设置当前日期
    let time = new Date();
    let year = time.getFullYear();
    let month = time.getMonth() + 1;
    let day = time.getDate();
    let name = '学生信息' + year + "-" + month + "-" + day;
    // 导出文件名
    const filename = state.excelTitle;
    // 通过id，获取导出的表格数据
    const wb = XLXS.utils.table_to_book(document.getElementById("table"), {
        raw: true,
    });
    const wbout = XLXS.write(wb, {
        bookType: "xlsx",
        bookSST: true,
        type: "array",
    });
    try {
        FileSaver.saveAs(
            new Blob([wbout], {
                type: "application/octet-stream",
            }),
            name + ".xlsx"
        );
    } catch (e) { }
}

</script>

<template>
    <el-container>
        <el-header height="50px">
            <el-form :inline="true" class="demo-form-inline">
                <el-form-item label="学生姓名">
                    <el-input placeholder="请输入学生姓名..." :prefix-icon="Search" v-model="searchModel.stu_name"></el-input>
                </el-form-item>
                <el-form-item label="所在班级">
                    <el-select v-model="searchModel.stu_cls_id">
                        <el-option :value="0" label="- 请选择 -"></el-option>
                        <el-option v-for="item in classStore.classList" :key="item.cls_id" :value="item.cls_id"
                            :label="item.cls_name"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="学生学历">
                    <el-select v-model="searchModel.stu_qualification">
                        <el-option :value="0" label="- 请选择 -"></el-option>
                        <el-option v-for="item in newList" :key="item.dic_id" :value="item.dic_id"
                            :label="item.dic_name">
                        </el-option>
                    </el-select>
                </el-form-item>
                <el-form-item>
                    <el-button :icon="Plus" type="primary" @click="addStu">新增</el-button>
                    <el-button :icon="Share" type="success" @click="distMult">批量分班</el-button>
                    <el-button :icon="Download" @click="exportClick()" type="warning">
                        导出学生信息</el-button>
                </el-form-item>
            </el-form>
        </el-header>
        <el-main>
            <el-table border :data="studentList" stripe ref="tableRef" id="table" @selection-change="isChecked">
                <el-table-column label="#" width="50" type="index" align="center" fixed />
                <el-table-column type="selection" width="50" fixed align="center" />
                <el-table-column label="学生姓名" width="100" height="590" fixed align="center" prop="stu_name" />
                <el-table-column label="班级" width="100" align="center" prop="stu_cls_id">
                    <template #default="{ row }">
                        <el-link v-if="classStore.classList.find(item => item.cls_id === row.stu_cls_id)">
                            <span
                                v-text="classStore.classList.find(item => item.cls_id === row.stu_cls_id)?.cls_name"></span>
                        </el-link>
                        <span v-else style="color: #999;">无班级</span>
                    </template>
                </el-table-column>
                <el-table-column label="存档照片" width="100" align="center" prop="stu_avatar">
                    <template #default="{ row }">
                        <el-popover trigger="click" placement="right"
                            popper-style="box-shadow: rgb(14 18 22 / 35%) 0px 10px 38px -10px, rgb(14 18 22 / 20%) 0px 10px 20px -15px; padding: 20px;">
                            <template #reference>
                                <el-button>预览</el-button>
                            </template>
                            <template #default>
                                <el-image :src="'image' + row.stu_avatar" />
                            </template>
                        </el-popover>
                    </template>
                </el-table-column>
                <el-table-column label="性别" width="100" align="center" prop="stu_sex">
                    <template #default="{ row }">
                        <el-tag v-if="row.stu_sex === 1">男</el-tag>
                        <el-tag v-else>女</el-tag>
                    </template>
                </el-table-column>
                <el-table-column label="联系电话" width="150" align="center" prop="stu_phone" />
                <el-table-column label="联系电话2" width="150" align="center" prop="stu_phone2" />
                <el-table-column label="出生日期" width="150" align="center" prop="stu_born">
                </el-table-column>
                <el-table-column label="学历" width="100" align="center" prop="stu_qualification">
                    <template #default="{ row }">
                        <span v-text="dictionaryStore.list.find(item => item.dic_id ===
                        row.stu_qualification)?.dic_name"></span>
                    </template>
                </el-table-column>
                <el-table-column label="毕业院校" width="180" align="center" prop="stu_school" />
                <el-table-column label="院校专业" width="180" align="center" prop="stu_major" />
                <el-table-column label="家庭住址" width="300" prop="stu_address" />
                <el-table-column label="备注" width="200" prop="stu_remark" />
                <el-table-column label="操作" width="350" fixed="right">
                    <template #default="{ row }">
                        <el-button :icon="EditPen" type="primary" @click="updateStu(row)">编辑</el-button>
                        <el-button :icon="Share" type="success" @click="distSingle(row)">分班</el-button>
                        <el-button :icon="PictureFilled" type="warning" @click="beginAvatarUpdate(row)">照片存档
                        </el-button>
                    </template>
                </el-table-column>
            </el-table>
        </el-main>
        <el-footer height="36px">
            <el-pagination background layout="prev, pager, next, jumper,->, sizes, total " :total="3"
                :page-sizes="[3, 6, 9, 12]" />
        </el-footer>
    </el-container>

    <!-- 新增/修改 -->
    <el-dialog :model-value="edit.isEdit" width="30%">
        <template #header>
            <span>{{  `学生编辑 - ${edit.isStu ? '新增' : '修改'}`  }}</span>
        </template>
        <el-form ref="formRef" :rules="rules" label-width="100px" :model="edit.model">
            <el-form-item prop="stu_name" label="学生姓名">
                <el-input placeholder="请输入学生姓名" v-model="edit.model.stu_name" />
            </el-form-item>
            <el-form-item prop="stu_sex" label="性别">
                <el-radio v-model="edit.model.stu_sex" :label="1">男</el-radio>
                <el-radio v-model="edit.model.stu_sex" :label="0">女</el-radio>
            </el-form-item>
            <el-form-item prop="stu_phone" label="联系电话">
                <el-input placeholder="请输入手机号" v-model="edit.model.stu_phone" />
            </el-form-item>
            <el-form-item prop="stu_phone2" label="备用电话">
                <el-input placeholder="请输入备用手机号" v-model="edit.model.stu_phone2" />
            </el-form-item>
            <el-form-item prop="stu_born" label="出生日期">
                <el-date-picker v-model="edit.model.stu_born" type="date" placeholder="选择出生日期" format="YYYY/MM/DD"
                    value-format="YYYY-MM-DD">
                </el-date-picker>
            </el-form-item>
            <el-form-item prop="stu_qualification" label="学历">
                <el-select v-model="edit.model.stu_qualification">
                    <el-option label=" - 请选择 - " :value="0" />
                    <el-option v-for="item in newList" :key="item.dic_id" :label="item.dic_name" :value="item.dic_id" />
                </el-select>
            </el-form-item>
            <el-form-item label="在读院校">
                <el-input placeholder="请输入在读院校（选填）" v-model="edit.model.stu_school" />
            </el-form-item>
            <el-form-item label="在校所学专业">
                <el-input placeholder="请输入在校所学专业（选填）" v-model="edit.model.stu_major" />
            </el-form-item>
            <el-form-item prop="stu_address" label="家庭住址">
                <el-input placeholder="请输入家庭住址" v-model="edit.model.stu_address" />
            </el-form-item>
            <el-form-item label="学生备注">
                <el-input placeholder="请输入备注" v-model="edit.model.stu_remark" />
            </el-form-item>
        </el-form>
        <template #footer>
            <el-button @click="edit.isEdit = false">取消</el-button>
            <el-button @click="save">确定</el-button>
        </template>
    </el-dialog>

    <!-- 分配班级 -->
    <el-dialog :model-value="edit.isClass" title="班级分配" width="30%" draggable>
        <el-form-item label="班级" :label-width="formLabelWidth">
            <el-select v-model="disModel.stu_cls_id">
                <el-option label=" - 请选择 - " :value="0"></el-option>
                <el-option label="无班级" :value="null"></el-option>
                <el-option v-for="item in classStore.classList" :key="item.cls_id" :label="item.cls_name"
                    :value="item.cls_id"></el-option>
            </el-select>
        </el-form-item>
        <template #footer>
            <el-button @click="edit.isClass = false">取消</el-button>
            <el-button @click="saveDist">分配</el-button>
        </template>
    </el-dialog>

    <!-- 照片存档 -->
    <el-dialog :model-value="isUpload" title="照片存档" width="30%" draggable>
        <div class="center">
            <el-upload action="/api/student/avatarupload" :headers="{ Authorization: authStore.token }" name="avatar"
                :file-list="fileList" list-type="picture-card" accept=".jpg,.png" :before-upload="beforeAvatarUpload"
                :on-success="successHandler">
                <el-icon class="avatar-uploader-icon">
                    <Plus />
                </el-icon>
            </el-upload>
            <span style="color:red; margin-top: 10px;">只能上传jpg/png且大小不能超过2M</span>
        </div>
        <template #footer>
            <el-button @click="isUpload = false">取消</el-button>
            <el-button @click="avatarUpdate">存档</el-button>
        </template>
    </el-dialog>
</template>

<style scoped>
/* 存档 */
.avatar-uploader .avatar {
    width: 178px;
    height: 178px;
    display: block;
}

.avatar-uploader .el-upload {
    border: 1px dashed var(--el-border-color);
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
    border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
    font-size: 28px;
    color: #9da2a8;
    width: 178px;
    height: 148px;
    text-align: center;
    border: 1px dashed #a3aab5;
}

.el-dialog .center {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
</style>